#include <cstdio>
#include "analisadorLexico.h"

#ifndef asah
class Id;
class Num;
class Literal;
class Program;
class VarList;
class NameDecl;
class FunctionList;
class TypeList;
class Type;
class PrimitiveType;
class IdType;
class StatementList;
class Statement;
class If;
class While;
class Switch;
class Break;
class Read;
class Println;
class CaseBlock;
class Return;
class ExpList;
class Exp;
class ExpAninhada;
class Call;
class Assign;
class RegisterExp;
class Array;
class Operation;
class Not;
class Sign;
class Boolean;
class Visitor;
class VisitorImpASA;
class VisitorImpARI;
class VisitorGeradorARI;
class VisitorGeradorMIPS;
class VisitorCanonizador;

class Frame;
class FrameMips;
class Fragment;
class Global;
class Procedure;
class FragmentList;
class InFrame;
class InReg;
class Stm;
class ExpARI;
class ExpARIList;
class Temp;
class TempList;
class Label;
class LabelList;
class AcessoLocal;
class ListaAcesso;
class Const;
class ConstF;
class LiteralARI;
class Name;
class BinOp;
class Mem;
class CallARI;
class Eseq;
class Move;
class Jump;
class CJump;
class Seq;

//O Frame decide se o dado local estara em um registrador ou em um temporario.
class Frame {

    public:
        int numParam;
        //Rotulo para o inicio do codigo do procedimento (nome)...
        Label* rotulo;
        //Lista de acessos locais (parametros e variaveis locais)...
        ListaAcesso* dadosLocais;

        virtual ~Frame();
        int offset;

        virtual void adicionaParam(int escapa, int tamanhoBytes) = 0;
        virtual void adicionaLocal(int escapa, int tamanhoBytes) = 0;

        virtual void accept(VisitorImpARI *visitor) = 0;
        virtual void accept(VisitorCanonizador* visitor) = 0;
        virtual void accept(VisitorGeradorMIPS* visitor) = 0;
};

class FrameMips : public Frame {
    public:
        FrameMips(Label* rotulo, ListaAcesso* dadosLocais);
        ~FrameMips();

        int sizeParam;

        //Essas funcoes decidem se um dado local estara em um registrador ou em um Frame...
        //Uma variavel escapa, ela tem que ser colocada no Frame...
        void adicionaParam(int escapa, int tamanhoBytes);
        void adicionaLocal(int escapa, int tamanhoBytes);

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Fragment {
    public:
        virtual ~Fragment();

        virtual void accept(VisitorImpARI *visitor) = 0;
        virtual void accept(VisitorCanonizador* visitor) = 0;
        virtual void accept(VisitorGeradorMIPS* visitor) = 0;
};

class Global : public Fragment {
    public:
        Label* label;
        int tipo;
        int tamanho;

        Global(Label* label, int tipo, int tamanho);
        virtual ~Global();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Procedure : public Fragment {
    public:
        Frame* frame;
        Stm* body;

        Procedure(Frame* frame, Stm* body);
        virtual ~Procedure();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class FragmentList : public Fragment {
	public:
		Fragment *fragment;
		FragmentList *proximo;

		FragmentList(Fragment *fragment, FragmentList *proximo);
		~FragmentList();

		void accept(VisitorImpARI *visitor);
		void accept(VisitorCanonizador* visitor);
		void accept(VisitorGeradorMIPS* visitor);
};

class Stm {
    public:
         ~Stm();

        virtual void accept(VisitorImpARI *visitor) = 0;
        virtual void accept(VisitorCanonizador* visitor) = 0;
        virtual void accept(VisitorGeradorMIPS* visitor) = 0;
};

class ExpARI : public Stm {
    public:
        ~ExpARI();

        virtual void accept(VisitorImpARI *visitor) = 0;
        virtual void accept(VisitorCanonizador* visitor) = 0;
        virtual void accept(VisitorGeradorMIPS* visitor) = 0;
};

class AcessoLocal : public ExpARI{
    public:

        char* rotulo;
        int type;
        int isParam;
        ~AcessoLocal();

        virtual void accept(VisitorImpARI* visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

//Para alocacao no Frame...
class InFrame : public AcessoLocal {
    public:
        int offset;
        int parametro;

        InFrame(int offset);
        ~InFrame();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

//Para alocacao no Registrador...
class InReg : public AcessoLocal {
    public:
        Temp* temp;

        InReg(Temp* temp);
        ~InReg();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class ExpARIList : public ExpARI {
	public:
        ExpARI* exp;
        ExpARIList* proximo;

        ExpARIList(ExpARI* exp, ExpARIList* proximo);
        ~ExpARIList();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

//Um temporario na maquina abstrata e similar a um registrador na maquina
//real, entretanto a maquina abstrata tem um numero infinito de registradores.
class Temp : public ExpARI{
    public:
        char* temp;

        Temp();
        Temp(char* temp);
        ~Temp();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class TempList {
    public:
        Temp* temp;
        TempList* proximo;

        TempList(Temp* temp, TempList* proximo);
        ~TempList();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class LabelList {
    public:
        Label* label;
        LabelList* proximo;

        LabelList(Label* label, LabelList* proximo);
        ~LabelList();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class ListaAcesso {
    public:
        AcessoLocal* acessoLocal;
        ListaAcesso* proximo;

        ListaAcesso(AcessoLocal* acessoLocal, ListaAcesso* proximo);
        ~ListaAcesso();

        void addItem(AcessoLocal* a);

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Const : public ExpARI {
    public:
        int valor;

        Const(int valor);
        ~Const();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class ConstF : public ExpARI {
    public:
        float valor;

        ConstF(float valor);
        ~ConstF();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class LiteralARI : public Fragment {
    public:
        Label* label;
        LiteralARI(Label *label);
        ~LiteralARI();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Name : public ExpARI {
    public:
        Label* label;
        int flagTemp;

        Name(Label* label);
        ~Name();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class BinOp : public ExpARI {
	public:
        int op;
        Stm *e1;
        Stm *e2;
        BinOp(int op, Stm* e1, Stm* e2);
        ~BinOp();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Mem : public ExpARI {
    public:
        ExpARI *e;
        Mem(ExpARI *e);
        ~Mem();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class CallARI : public ExpARI {
    public:
        int canonizado;
        ExpARI* funcao;
        ExpARIList* argumentos;

        int syscallRead;
        int syscallWrite;

        CallARI(ExpARI* funcao, ExpARIList* argumentos);
        ~CallARI();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Eseq : public ExpARI {
   	public:
        Stm* stm;
        ExpARI* exp;

        Eseq(Stm* stm, ExpARI* exp);
        ~Eseq();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Move : public ExpARI {
	public:
        ExpARI* t;
        ExpARI* e;

        Move(ExpARI* e, ExpARI* t);
        ~Move();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

/*class EXP : public Stm {
	public:
        ExpARI *expARI;

        EXP(ExpARI* expARI);
        ~EXP();

        void accept(VisitorImpARI *visitor);
};*/


class Jump : public Stm {
	public:
        ExpARI* exp;

        Jump(ExpARI* exp);
        ~Jump();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};


class CJump : public Stm {
	public:
        int op;
        ExpARI* e1; //era stm
        ExpARI* e2; //era stm
        Label* t;
        Label* f;

        CJump(int op, ExpARI* exp1, ExpARI* e2, Label* t, Label* f);
        ~CJump();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Seq : public Stm {
	public:
        Stm* s1;
        Stm* s2;

        Seq(Stm* s1, Stm* s2);
        ~Seq();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

//Representa o endereco de codigo nesse local. Especifica a posicao do rotulo
//no codigo assembly. A expressao 'nome' podera ser o alvo de JUMP, CJUMP e CALL.
class Label : public Stm {
    public:
        char* nome;

        Label();
        Label(char* nome);
        ~Label();

        void accept(VisitorImpARI *visitor);
        void accept(VisitorCanonizador* visitor);
        void accept(VisitorGeradorMIPS* visitor);
};

class Program {
    public:
        FunctionList* functionList;
        TypeList* typeList;
        VarList* varList;
        int linha;

        Program(FunctionList* functionList, TypeList* typeList, VarList* varList, int linha);
        ~Program();

        void accept(Visitor* visitor);
        void accept(VisitorGeradorARI* visitor);
};

class VarList {
    public:
        NameDecl* nameDecl;
        VarList* varList;
        int linha;

        VarList(NameDecl* nameDecl, VarList* varList,int linha);
        ~VarList();

        void accept(Visitor* visitor);
        void accept(VisitorGeradorARI* visitor);
};

class NameDecl {
    public:
        Type* type;
        Id* id;
        int linha;

        NameDecl(Type* type, Id* id,int linha);
        ~NameDecl();

        void accept(Visitor* visitor);
        ListaAcesso* accept(VisitorGeradorARI* visitor);
};

class FunctionList {
    public:
        Type* type;
        Id* id;
        VarList* varList1;
        VarList* varList2;
        StatementList* statementList;
        FunctionList* functionList;
        int linha;

        FunctionList(Type* type, Id* id, VarList* varList1, VarList* varList2, StatementList* statementList, FunctionList* functionList,int linha);
        ~FunctionList();
        char* getNome();
        void accept(Visitor* visitor);
        void accept(VisitorGeradorARI* visitor);
};

class TypeList {
    public:
        VarList* varList;
        Id* id;
        TypeList* typeList;
        int linha;

        TypeList(VarList* varList, Id* id, TypeList* typeList,int linha);
        ~TypeList();

        void accept(Visitor* visitor);
        void accept(VisitorGeradorARI* visitor);
};

class Type {
    public:
        char* size;
        int linha;

        virtual ~Type();

        //Solucao adotada para que o metodo
        //cloneType possa saber de que tipo
        //eh o Type a ser clonado.
        virtual int tipoSubClasse() = 0;

        virtual int accept(Visitor* visitor) = 0;
        virtual ExpARI* accept(VisitorGeradorARI* visitor) = 0;
};

class PrimitiveType : public Type {
    public:
        int primitive;

        PrimitiveType(int primitive, char* size, int linha);
        ~PrimitiveType();

        int tipoSubClasse();
        int accept(Visitor* visitor);
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class IdType : public Type {
    public:
        Id* id;

        IdType(Id* id, char* size, int linha);
        ~IdType();

        int tipoSubClasse();
        int accept(Visitor* visitor);
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Statement {
    public:
        Statement();
        int linha;
        virtual ~Statement();

        virtual int accept(Visitor* visitor) = 0;
        virtual Stm* accept(VisitorGeradorARI* visitor) = 0;
};

class StatementList : public Statement {
    public:
        Statement* statement;
        StatementList* statementList;

        StatementList(Statement* statement, StatementList* statementList,int linha);
        ~StatementList();

        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class If : public Statement {
    public:
        Exp* exp;
        Statement *statement1, *statement2;

        If(Exp* exp, Statement* statement1, Statement* statement2,int linha);
        ~If();

        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class While : public Statement {
    public:
        Exp* exp;
        Statement* statement;

        While(Exp* exp, Statement* statement,int linha);
        ~While();

        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class Switch : public Statement {
    public:
        Exp* exp;
        CaseBlock* caseBlock;

        Switch(Exp* exp, CaseBlock* caseBlock,int linha);
        ~Switch();

        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class Break : public Statement {
    public:
        Break();
        ~Break();
        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class Read : public Statement {
    public:
        Exp* exp;

        Read(Exp* exp,int linha);
        ~Read();

        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class Println : public Statement {
    public:
        ExpList* expList;

        Println(ExpList* expList,int linha);
        ~Println();
        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class CaseBlock : public Statement {
    public:
        Num* num;
        StatementList* statementList;
        CaseBlock* caseBlock;

        CaseBlock(Num* num, StatementList* statementList, CaseBlock* caseBlock,int linha);
        ~CaseBlock();

        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class Return : public Statement {
    public:
        Exp* exp;

        Return(Exp* exp,int linha);
        ~Return();

        int accept(Visitor* visitor);
        Stm* accept(VisitorGeradorARI* visitor);
};

class ExpList : public Statement {
    public:
        Exp* exp;
        ExpList* expList;

        ExpList(Exp* exp, ExpList* expList, int linha);
        ~ExpList();
        char* getNome();
        int accept(Visitor* visitor);
        ExpARIList* accept(VisitorGeradorARI* visitor);
};

class Exp : public Statement {
    public:

        Exp();
        ~Exp();
        virtual char* getNome() = 0;
        virtual int lValue() = 0;
        virtual int accept(Visitor* visitor) = 0;
        virtual ExpARI* accept(VisitorGeradorARI* visitor) = 0;
};

class ExpAninhada : public Exp {
    public:
        Exp* exp1;
        Exp* exp2;

        ExpAninhada(Exp* exp1, Exp* exp2,int linha);
        ~ExpAninhada();
        char* getNome();
        int lValue();
        int accept(Visitor* visitor);
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Id : public Exp {
    public:
        char *id;

        Id(char* id,int linha);
        ~Id();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Num : public Exp {
    public:
        char *num;
        Num(char* num,int linha);
        ~Num();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Literal : public Exp {
    public:
        char *literal;
        Literal(char* literal,int linha);
        ~Literal();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Call : public Exp {
    public:
        Id* id;
        ExpList* expList;

        Call(Id* id, ExpList* expLis,int linha);
        ~Call();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Assign : public Exp {
    public:
        Exp *exp1, *exp2;

        Assign(Exp* exp1, Exp* exp2,int linha);
        ~Assign();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class RegisterExp : public Exp {
    public:
        Exp* exp;
        Id* id;

        RegisterExp(Exp* exp, Id* id,int linha);
        ~RegisterExp();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Array : public Exp {
    public:
        Exp *exp1, *exp2;

        Array(Exp* exp1, Exp* exp2,int linha);
        ~Array();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

//Classe abstrata que abrange todas as operacoes
//como adicao, multiplicao, entre outras, variando
//apenas o token que indica a qual operacao
//uma instancia desta classe representa.
class Operation : public Exp {
    public:
        int tokenOperacao;
        Exp *exp1, *exp2;

        Operation(int tokenOperacao, Exp* exp1, Exp* exp2,int linha);
        ~Operation();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Not : public Exp {
    public:
        Exp* exp;

        Not(Exp* exp,int linha);
        ~Not();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Sign : public Exp {
    public:
        Exp* exp;
        int token;

        Sign(Exp* exp, int token,int linha);
        ~Sign();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Boolean : public Exp {
    public:
        int token;

        Boolean(int token,int linha);
        ~Boolean();
        int lValue();
        int accept(Visitor* visitor);
        char* getNome();
        ExpARI* accept(VisitorGeradorARI* visitor);
};

class Visitor {
	public:
        virtual int visit(Id* id) = 0;
        virtual int visit(Num* num) = 0;
        virtual int visit(Literal* literal) = 0;
        virtual void visit(Program* program) = 0;
        virtual void visit(VarList* varList) = 0;
        virtual void visit(NameDecl* nameDecl) = 0;
        virtual void visit(FunctionList* functionList) = 0;
        virtual void visit(TypeList* typeList) = 0;
        virtual int visit(Type* type) = 0;
        virtual int visit(PrimitiveType* primitiveType) = 0;
        virtual int visit(IdType* idType) = 0;
        virtual int visit(StatementList* statementList) = 0;
        virtual int visit(Statement* statement) = 0;
        virtual int visit(If* _if) = 0;
        virtual int visit(While* _while) = 0;
        virtual int visit(Switch* _switch) = 0;
        virtual int visit(Break* _break) = 0;
        virtual int visit(Read* _read) = 0;
        virtual int visit(Println* _println) = 0;
        virtual int visit(CaseBlock* caseBlock) = 0;
        virtual int visit(Return* _return) = 0;
        virtual int visit(ExpList* expList) = 0;
        virtual int visit(Exp* exp) = 0;
        virtual int visit(ExpAninhada* expAninhada) = 0;
        virtual int visit(Call* call) = 0;
        virtual int visit(Assign* assign) = 0;
        virtual int visit(RegisterExp* registerExp) = 0;
        virtual int visit(Array* array) = 0;
        virtual int visit(Operation* operation) = 0;
        virtual int visit(Not* _not) = 0;
        virtual int visit(Sign* sign) = 0;
        virtual int visit(Boolean* boolean) = 0;
};

class VisitorImpASA : public Visitor{
	public:
		int visit(Id* id);
        int visit(Num* num);
        int visit(Literal* literal);
        void visit(Program* program);
        void visit(VarList* varList);
        void visit(NameDecl* nameDecl);
        void visit(FunctionList* functionList);
        void visit(TypeList* typeList);
        int visit(Type* type);
        int visit(PrimitiveType* primitiveType);
        int visit(IdType* idType);
        int visit(StatementList* statementList);
        int visit(Statement* statement);
        int visit(If* _if);
        int visit(While* _while);
        int visit(Switch* _switch);
        int visit(Break* _break);
        int visit(Read* _read);
        int visit(Println* _println);
        int visit(CaseBlock* caseBlock);
        int visit(Return* _return);
        int visit(ExpList* expList);
        int visit(Exp* exp);
        int visit(ExpAninhada* expAninhada);
        int visit(Call* call);
        int visit(Assign* assign);
        int visit(RegisterExp* registerExp);
        int visit(Array* array);
        int visit(Operation* operation);
        int visit(Not* _not);
        int visit(Sign* sign);
        int visit(Boolean* boolean);
};

class VisitorGeradorARI {
	public:
        void visit(Program* program);
        void visit(VarList* varList);
        ListaAcesso* visit(NameDecl* nameDecl);
        void visit(FunctionList* functionList);
        void visit(TypeList* typeList);
        ExpARI* visit(Type* type);
        ExpARI* visit(PrimitiveType* primitiveType);
        ExpARI* visit(IdType* idType);
        Stm* visit(StatementList* statementList);
        Stm* visit(Statement* statement);
        Stm* visit(If* _if);
        Stm* visit(While* _while);
        Stm* visit(Switch* _switch);
        Stm* visit(Break* _break);
        Stm* visit(Read* _read);
        Stm* visit(Println* _println);
        Stm* visit(CaseBlock* caseBlock);
        Stm* visit(Return* _return);
        ExpARIList* visit(ExpList* expList);
        ExpARI* visit(Exp* exp);
        ExpARI* visit(ExpAninhada* expAninhada);
        ExpARI* visit(Call* call);
        ExpARI* visit(Assign* assign);
        ExpARI* visit(RegisterExp* registerExp);
        ExpARI* visit(Array* array);
        ExpARI* visit(Operation* operation);
        ExpARI* visit(Not* _not);
        ExpARI* visit(Sign* sign);
        ExpARI* visit(Boolean* boolean);
        ExpARI* visit(Id* id);
        ExpARI* visit(Num* num);
        ExpARI* visit(Literal* literal);
};

class VisitorImpARI {
    public:
        void visit(Frame* frame);
        void visit(FrameMips* frameMips);
        void visit(Fragment* fragment);
        void visit(Global* global);
        void visit(Procedure* procedure);
        void visit(FragmentList* fragmentList);
        void visit(InFrame* inFrame);
        void visit(InReg* inReg);
        void visit(Stm* stm);
        void visit(ExpARI* expARI);
        void visit(ExpARIList* expARIList);
        void visit(Temp* temp);
        void visit(TempList* tempList);
        void visit(Label* label);
        void visit(LabelList* labelList);
        void visit(AcessoLocal* acessoLocal);
        void visit(ListaAcesso* listaAcesso);
        void visit(Const* _const);
        void visit(ConstF* constf);
        void visit(LiteralARI* literalARI);
        void visit(Name* name);
        void visit(BinOp* binOP);
        void visit(Mem* mem);
        void visit(CallARI* callARI);
        void visit(Eseq* eseq);
        void visit(Move* move);
        void visit(Jump* jump);
        void visit(CJump* cJump);
        void visit(Seq* seq);
};
#endif
#define asah
